/**
 * @name uploader/index
 * @desc 断点续传上传附件组件
 * @author yangliu at 2019-10-23
 * @version V1.0.0
 */

import React, { Component } from 'react';

import { DeleteOutlined, DownloadOutlined, EyeOutlined, InboxOutlined } from '@ant-design/icons';
import { notification, Row, Col, Input, Button, message } from 'antd';
import { formatMessage } from '@/utils/i18n-transform';
import cn from 'classnames';
import { api } from '@/services';
import { ResponseType } from 'common-module';

import { PlusOutlined, SwapOutlined } from '@ant-design/icons';

// @ts-ignore
import _ from 'lodash';
import Resumable from './resumable';
import './indes.less';
import { ImgView } from './ImgView';

interface File {
  name: string;
  id: string;
}
interface UpProps {
  uploadUrl?: string; // 上传的url
  downloadUrl?: string; // 下载的url
  sigle?: boolean; // 是否是单文件上传
  draggable?: boolean; // 是否支持拖动
  disabled?: boolean; // 是否禁用
  editable?: boolean; // 是否可编辑
  fileList?: any; // fileList
  multiple?: any; // 支持上传多个
  deleteCb?: (id: string) => void; // 删除的回调
  uploadCb?: (file: File) => void; // 上传后的回调
  errorCb?: (obj: any) => void; // 发生错误后的回调
  justUpload?: boolean; // 是否只是上传,fileList上传组件自己控制
  justImg?: boolean; // 是否只是上传图片
  onChange?: (fileList: File[]) => void; // 自定义表单回调
  value?: File[]; // 文件列表
  fileType?: string[];
  [propsName: string]: any;
}
interface UpStates {
  fileList?: File[];
  picVisible: boolean;
  picId?: any;
}
export default class Uploader extends Component<UpProps, UpStates> {
  uploader: any = null;

  browseButton: any = null;

  draggable: any = null;

  constructor(props: UpProps) {
    super(props);
    this.browseButton = React.createRef();
    this.draggable = React.createRef();
    this.state = {
      picVisible: false,
      picId: null,
    };
  }

  static getFileList = (justImg: boolean | undefined, value: any) => {
    let fileList = [];

    if (justImg) {
      fileList = value
        ? typeof value === 'string'
          ? [{ id: value, name: '' }]
          : value.map((item: any) => {
              if (typeof item === 'string') {
                return { id: item, name: '' };
              }
              return item;
            })
        : [];
    } else {
      fileList = value || [];
    }

    return fileList;
  };

  static getDerivedStateFromProps(props: UpProps) {
    if (
      !_.isEqual(props.fileList, Uploader.getFileList(props.justImg, props.value)) &&
      !props.justUpload
    ) {
      return {
        fileList: Uploader.getFileList(props.justImg, props.fileList),
      };
    }
    // Return null if the state hasn't changed
    return null;
  }

  componentDidMount() {
    this.setResumeUpload();
    // const fileList = Uploader.getFileList(this.props.justImg, this.props.value);
    // this.setState({
    //     fileList
    // });
  }
  // shouldComponentUpdate(nextProps: Readonly<UpProps>, nextState: Readonly<UpStates>, nextContext: any): boolean {
  //
  //   return false;
  // }
  // componentWillReceiveProps(nextProps:Readonly<any>): void {
  //     if (nextProps.value !== this.props.value){
  //         const fileList = Uploader.getFileList(nextProps.justImg, nextProps.value);
  //         this.setState({
  //             fileList
  //         });
  //     }
  // }

  // 设置unique Id
  uuid = (len: number, radix: number) => {
    const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
    // tslint:disable-next-line: no-shadowed-variable
    const uuid = [];
    let i = 0;
    radix = radix || chars.length;

    if (len) {
      // Compact form
      for (i = 0; i < len; i++) {
        // tslint:disable-next-line: no-bitwise
        uuid[i] = chars[0 | (Math.random() * radix)];
      }
    } else {
      // rfc4122, version 4 form
      let r = 0;

      // rfc4122 requires these characters
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
      uuid[14] = '4';

      // Fill in random data.  At i==19 set the high bits of clock sequence as
      // per rfc4122, sec. 4.1.5
      for (i = 0; i < 36; i++) {
        if (!uuid[i]) {
          // tslint:disable-next-line: no-bitwise
          r = 0 | (Math.random() * 16);
          // tslint:disable-next-line: triple-equals tslint:disable-next-line: no-bitwise
          uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
        }
      }
    }
    return uuid.join('');
  };

  // 引入resumeTable方法
  setResumeUpload = () => {
    const { sigle, justImg, fileType } = this.props;
    const userInfo = JSON.parse(localStorage.getItem('currentUser') || '');
    const accessToken: string = (userInfo && userInfo.accessToken) || null;
    const that = this;
    const temp = fileType && fileType.split(',');
    const fileTypeTemp = justImg ? ['image/*'] : temp;
    this.uploader = new Resumable({
      target: this.props.uploadUrl || api.ocrUpload,
      chunkSize: 512 * 1024,
      maxChunkRetries: 2,
      simultaneousUploads: 1,
      testChunks: true,
      throttleProgressCallbacks: 1,
      method: 'octet',
      permanentErrors: [400, 404, 415, 500, 501, 401],
      fileType: fileTypeTemp,
      maxFiles: sigle ? 1 : 1000,
      generateUniqueIdentifier: (file: any, event: any) => {
        const relativePath = file.webkitRelativePath || file.fileName || file.name; // Some confusion in different versions of Firefox
        const { size } = file;
        return `${size}-${relativePath.replace(/[^0-9a-zA-Z_-]/gim, '')}-${this.uuid(8, 16)}`;
      },
      headers: {
        Authorization: !accessToken ? '' : `Bearer ${accessToken}`,
      },
    });

    // if resumable is not supported aka IE
    if (!this.uploader.support) location.href = 'http://browsehappy.com/';

    // 设置上传的目标dom元素
    const browseButton = that.props.draggable ? this.draggable.current : this.browseButton.current;
    if (!that.props.disabled) {
      this.uploader.assignBrowse(browseButton);
      // 支持拖动
      if (that.props.draggable) {
        this.uploader.assignDrop(this.draggable.current);
      }
    }
    this.uploader.on('fileAdded', (fileEvent: any, event: any) => {
      that.fileAdded(fileEvent);
    });
    this.uploader.on('fileProgress', (file: any) => {
      // var progress = Math.floor(file.progress() * 100);
    });
    this.uploader.on('fileSuccess', (fileEvent: any, res: any) => {
      const result = JSON.parse(res || '');

      if (!result || !result.success) {
        message.error(result?.message || '上传错误');
      }
      that.fileSuccess(fileEvent.file, result);
    });
    this.uploader.on('error', (fileEvent: any, res: any) => {
      if (that.props.errorCb) {
        that.props.errorCb(res);
      }
    });
  };

  // 新增文件
  fileAdded = (fileEvent: any) => {
    const { justImg, value } = this.props;
    const fileList = Uploader.getFileList(justImg, value);
    const nowFile = fileEvent.file;
    let isRepeat: Boolean = false;
    // // 判断是否是单文件
    // if (sigle && fileList.length > 0) {
    // 	notification.warning({
    // 		message: '温馨提示',
    // 		description: '单文件上传，请删除再上传',
    // 	});
    // 	fileEvent.cancel();
    // 	return;
    // }
    // 判断是否重复上传
    fileList.forEach((file: any) => {
      if (nowFile.name === file.name) {
        notification.warning({
          message: '系统提示',
          description: '该文件已上传,请从新选择',
        });
        isRepeat = true;
        fileEvent.cancel();
      }
    });
    if (!isRepeat) {
      fileEvent.upload();
    }
  };

  // 文件上传成功
  fileSuccess = (file: any, res: ResponseType) => {
    const fileObj = { name: file.name, id: res.result };
    const { justUpload, onChange, sigle, value, justImg } = this.props;
    const fileList = Uploader.getFileList(justImg, value);
    const newFileList = [...fileList];
    if (justUpload) {
      if (sigle) {
        this.setState({
          fileList: [fileObj],
        });
      } else {
        fileList.push({ name: file.name, id: res.result });
        this.setState({ fileList: [...newFileList, fileObj] });
      }
    }
    if (this.props.uploadCb) {
      this.props.uploadCb(fileObj);
    }

    onChange && onChange(sigle ? [fileObj] : [...newFileList, fileObj]);
  };

  // 删除文件
  fileDelete = (id: string) => {
    const { onChange, sigle, justImg, value } = this.props;
    const fileList = Uploader.getFileList(justImg, value);
    const newFileList = fileList.filter((item: any) => item.id !== id);
    // this.setState({
    //     fileList: newFileList,
    // });
    if (this.props.deleteCb) {
      this.props.deleteCb(id);
    } else {
      onChange && onChange(sigle ? [] : newFileList);
    }
  };

  fileDis = () => {
    this.setState({
      picVisible: false,
    });
  };

  fileView = (id: string) => {
    const { picVisible, picId } = this.state;
    const url = `${api.ocrFileDownload}/${id}`;
    // return null;
    return picVisible && picId === id ? (
      <ImgView handleCancel={() => this.fileDis()} previewImgUrl={url} />
    ) : null;
  };

  render() {
    // const { fileList } = this.state;
    const { draggable, disabled, editable, justImg, sigle, value, multiple } = this.props;
    const fileList = Uploader.getFileList(justImg, value) || [];
    return (
      <div style={{ width: '100%' }}>
        <div className="file-upload-wrapper">
          {justImg ? (
            <div
              className={cn(
                'img-operate',
                sigle ? 'sigle-img' : '',
                fileList && fileList.length && sigle ? 'has-img' : '',
              )}
            >
              <div className="img-list">
                {fileList && fileList.length
                  ? fileList.map((file: any, i: number) => {
                      console.log(file);
                      console.log(fileList);
                      return (
                        <img src={`${this.props.downloadUrl || api.ocrDownload}/${file.id}`} />
                      );
                    })
                  : null}
              </div>
              <span
                className={cn('upload-img', disabled ? 'disabled' : '')}
                ref={this.browseButton}
              >
                {!sigle || !fileList || !fileList.length ? <PlusOutlined /> : <SwapOutlined />}
              </span>
            </div>
          ) : (
            <React.Fragment>
              <Row style={{ width: '100%' }}>
                {!disabled ? (
                  <Col span={24}>
                    <div className="file-operate">
                      <div className="btns">
                        {draggable ? null : (
                          <div
                            className={cn('upload', disabled ? 'disabled' : '')}
                            ref={this.browseButton}
                          >
                            <div className="title">
                              {formatMessage({ id: 'application.form.attachments.add' })}
                            </div>
                            <Input
                              placeholder={formatMessage({
                                id: 'application.form.attachments.add.please',
                              })}
                              multiple={multiple}
                            />
                            <Button type="primary">
                              {formatMessage({ id: 'application.form.attachments.scan' })}
                            </Button>
                          </div>
                        )}
                      </div>
                      {draggable ? (
                        <div
                          className={cn('drop-zone', disabled ? 'disabled' : '')}
                          ref={this.draggable}
                        >
                          <p className="upload-drag-icon">
                            <InboxOutlined />
                          </p>
                          <p className="upload-text">{formatMessage({ id: 'uploadInfo' })}</p>
                          <p className="upload-hint">
                            {formatMessage({ id: 'SupportExtension' })}：.rar .zip .doc .docx .pdf
                            .xml .jpg .png...
                          </p>
                        </div>
                      ) : null}
                    </div>
                  </Col>
                ) : null}
                <Col span={24}>
                  <div className="file-List" style={{ borderLeft: 'none' }}>
                    {fileList && fileList.length > 0 ? (
                      fileList.map((file: File, i: number) => {
                        const iconStyle = cn(
                          'file-icon',
                          file.name ? [`file-icon-${file.name.split('.')[1]}`] : '',
                        );
                        return (
                          <div className="file" key={i}>
                            {this.fileView(file.id)}
                            <div className="info">
                              <span className={iconStyle} />
                              <span>{file.name}</span>
                            </div>
                            {disabled === false || editable === true ? (
                              <div className="operate">
                                <DownloadOutlined
                                  onClick={() => {
                                    window.open(
                                      `${this.props.downloadUrl || api.ocrDownload}/${file.id}`,
                                    );
                                  }}
                                />
                                <DeleteOutlined
                                  onClick={() => {
                                    this.fileDelete(file.id);
                                  }}
                                />
                                <EyeOutlined
                                  onClick={() => {
                                    this.setState({
                                      picVisible: true,
                                      picId: file.id,
                                    });
                                  }}
                                />
                              </div>
                            ) : (
                              <div className="operate">
                                <DownloadOutlined
                                  onClick={() => {
                                    window.open(
                                      `${this.props.downloadUrl || api.ocrDownload}/${file.id}`,
                                    );
                                  }}
                                />
                                <EyeOutlined
                                  onClick={() => {
                                    this.setState({
                                      picVisible: true,
                                      picId: file.id,
                                    });
                                  }}
                                />
                              </div>
                            )}
                          </div>
                        );
                      })
                    ) : (
                      <span className="noFile">
                        {formatMessage({ id: 'application.form.attachments.nothave' })}
                      </span>
                    )}
                  </div>
                </Col>
              </Row>
            </React.Fragment>
          )}
        </div>
      </div>
    );
  }
}
